package SolR;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.apache.solr.client.solrj.impl.XMLResponseParser;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;

import Main.Pair;


public abstract class SolRManager<Type> {

	protected CommonsHttpSolrServer server;

	public SolRManager(String urlStr,String coreName) throws MalformedURLException{
		
		URL url = new URL(new URL(urlStr), coreName);
		server = new CommonsHttpSolrServer(url); 
		
		
//		server = new CommonsHttpSolrServer( url );
		
		server.setFollowRedirects(false);  // defaults to false
		
		
		// allowCompression defaults to false.
		// Server side must support gzip or deflate for this to have any effect.
		server.setAllowCompression(true);
		
		server.setMaxRetries(1); // defaults to 0.  > 1 not recommended.
		
		server.setParser(new XMLResponseParser()); // binary parser is used by default
	}
	
	public SolRManager(String urlStr) throws MalformedURLException{
				
		server = new CommonsHttpSolrServer( urlStr );
		
		server.setFollowRedirects(false);  // defaults to false
		
		
		// allowCompression defaults to false.
		// Server side must support gzip or deflate for this to have any effect.
		server.setAllowCompression(true);
		
		server.setMaxRetries(1); // defaults to 0.  > 1 not recommended.
		
		server.setParser(new XMLResponseParser()); // binary parser is used by default
	}

	public void deleteAll() throws SolrServerException, IOException{
		server.deleteByQuery( "*:*" );// delete everything!
		server.commit();
	}
	
	public void addDocument(Collection<Type> types) throws SolrServerException, IOException{
		
	
		Collection<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
		
		for(Type type : types){
			SolrInputDocument doc1 = new SolrInputDocument();
			addType(doc1, type);
			docs.add( doc1 );
		}
   
//		docs.add( doc1 );
		
		server.add( docs );//doc1=>docs
		server.commit();
	}
	
	public void addDocument(Type type) throws SolrServerException, IOException{
		SolrInputDocument doc1 = new SolrInputDocument();
		
		addType(doc1, type);
   
		Collection<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
		docs.add( doc1 );
		server.add( docs );//doc1=>docs
		server.commit();
	}
	
	public void addDocument(Type type1,Type type2) throws SolrServerException, IOException{
		SolrInputDocument doc1 = new SolrInputDocument();
		SolrInputDocument doc2 = new SolrInputDocument();
		
		addType(doc1, type1);
		addType(doc2, type2);
   
		Collection<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
		docs.add( doc1 );
		docs.add( doc2 );
		server.add( docs );//doc1=>docs
		server.commit();
	}

	public Pair<Long,LinkedList<Type>> query(String query,int page) throws SolrServerException{
//		System.out.println("SolRMeneger:Query 1 "+query);//TODO
		query=query.replace("\\", "");
//		System.out.println("SolRMeneger:Query 2 "+query);//TODO
		SolrQuery query1 = new SolrQuery();
		query1.setQuery(query);
		LinkedList<Type> ans=new LinkedList<Type>();

		query1.setHighlight(true).setHighlightSnippets(1); //set other params as needed
		query1.setParam("hl.fl", "content");
		query1.setStart(10*page);
//		query1.setFields("id");
		//query1.addFilterQuery("id");

		
		System.out.println("SolRMeneger.query="+query+" query1="+query1);//TODO
		
		QueryResponse queryResponse = server.query(query1);
		Iterator<SolrDocument> iter = queryResponse.getResults().iterator();

		while (iter.hasNext()) {
			SolrDocument resultDoc = iter.next();
			ans.add(getType(resultDoc));
		}
		long lastSearchCountPage=((SolrDocumentList)queryResponse.getResponse().getVal(1)).getNumFound();
		return new Pair<Long, LinkedList<Type>>(lastSearchCountPage, ans);
	}
	
	public Pair<Long,LinkedList<Type>> queryAll(int page) throws SolrServerException{
		return query("*:*",page);
	}

	protected abstract Type getType(SolrDocument resultDoc);
	protected abstract void addType(SolrInputDocument doc,Type type);
	
	protected Object getField(String field,SolrDocument resultDoc){
//		System.out.println("AAAAAA "+resultDoc.getFieldValue(field).getClass());//TODO
//		System.out.println("AAAAAA "+resultDoc.getFieldValue(field));//TODO
		return resultDoc.getFieldValue(field);
	}
	
	protected void addField(String field,SolrDocument doc,Object value){
		doc.addField(field,value);
	}
}
